<template>
  <div ref="terminal" id="terminal" class="terminal-container"></div>
</template>

<script setup>
import {
  ref,
  onMounted,
  onBeforeUnmount,
  defineEmits,
  defineProps,
  watch,
} from "vue";
// import socketio from "socket.io-client";
import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit";
import { WebLinksAddon } from "xterm-addon-web-links";
import "xterm/css/xterm.css";
import { debounce } from "lodash";

// 初始化 Socket 链接
// const socket = socketio("http://backend-url");

// 定义终端状态
const terminal = ref(null);
const fitAddon = new FitAddon();
const webLinksAddon = new WebLinksAddon();
const term = ref(null);
const commandHistory = ref([]);
let historyIndex = -1;
let promptLength = 0;
let currentInput = "";
const emit = defineEmits(["handleTer", "sendCommand"]);

const props = defineProps(["terminalHeight", "connectMsg"]);
// 创建时间戳
const getTimestamp = () => {
  const date = new Date();
  let curtime = `${date.toLocaleString()}`;
  promptLength = curtime.length + 5;
  console.log(333333333, curtime, promptLength);
  return `\x1b[38;5;242m[${date.toLocaleString()}]\x1b[0m `;
};
// 光标初始位置
let cursorPosition = 0;
// 输出提示符
const writePrompt = () => {
  const prompt = getTimestamp() + "> " + "\x1b[38;5;117m";
  term.value.write(prompt);
};
watch(
  () => props.terminalHeight,
  () => {
    console.log(333333333222222, props.terminalHeight);
    const terminalDOM =
      document.getElementsByClassName("terminal-container")[0];
    terminalDOM.style.height = `${props.terminalHeight}vh`;
  }
);

// 初始化终端
const initTerm = () => {
  term.value = new Terminal({
    rendererType: "canvas",
    rows: 10,
    theme: {
      foreground: "#ECECEC",
      background: "#1E1E1E",
      cursor: "#ECECEC",
    },
    cursorBlink: false,
    // cursorStyle?: 'block' | 'underline' | 'bar'; // 光标的样式
    cursorStyle: "block", // 光标的样式
  });

  term.value.open(terminal.value);
  term.value.loadAddon(fitAddon);
  term.value.loadAddon(webLinksAddon);
  fitAddon.fit();
  // term.value.onCursorMove();
  // 初始化提示符
  // let cursorPosition = 0;
  writePrompt();

  cursorPosition = term.value.buffer.active.cursorX;
  // 键盘事件处理
  // term.value.onKey((e) => {
  //   const ev = e.domEvent;
  //   const key = ev.key;

  //   switch (key) {
  //     case "Enter":
  //       term.value.write("\r\n");
  //       handleCommand(currentInput);
  //       emit("sendCommand", currentInput);
  //       currentInput = "";
  //       writePrompt();
  //       break;

  //     case "Backspace":
  //       if (
  //         currentInput.length > 0 &&
  //         term.value.buffer.active.cursorX > promptLength
  //       ) {
  //         currentInput = currentInput.slice(0, -1);
  //         // term.value.write("\b \b");
  //         // term.value.write("\x1b[P");
  //         // 使用终端控制序列进行三步操作：
  //         term.value.write(
  //           "\x1B[D" + // 1. 左移光标
  //             "\x1B[P" + // 2. 删除当前字符（相当于vim的x命令）
  //             "\x1B[s" + // 3. 保存光标位置（可选）
  //             "\x1B[u" // 5. 恢复光标位置（配合第3步）
  //         );
  //         // "\x1B[K" + // 4. 清除从光标到行尾的内容（防止残留字符）
  //       }
  //       break;

  //     case "ArrowUp":
  //       navigateHistory(-1);
  //       break;

  //     case "ArrowDown":
  //       navigateHistory(1);
  //       break;

  //     case "ArrowLeft":
  //       console.log("term", term.value.buffer.active, cursorPosition);

  //       if (term.value.buffer.active.cursorX > promptLength) {
  //         term.value.write("\x1B[D"); // 移动光标向左
  //       }

  //       break;

  //     case "ArrowRight":
  //       if (
  //         term.value.buffer.active.cursorX <
  //         promptLength + currentInput.length
  //       ) {
  //         term.value.write("\x1B[C"); // 移动光标向右
  //       }
  //       break;
  //     default:
  //       if (key.length === 1) {
  //         // 计算插入位置
  //         let index = term.value.buffer.active.cursorX - promptLength;
  //         let currentLength = currentInput.length - index;
  //         // 创建新字符串：前半部分 + 插入字符 + 后半部分
  //         let newInput =
  //           currentInput.slice(0, index) + key + currentInput.slice(index);

  //         // 更新 currentInput
  //         currentInput = newInput;
  //         console.log("currentInput", currentInput, key);
  //         // 将字符打印到终端，并更新光标位置
  //         if (index < currentInput.length - 1) {
  //           console.log();

  //           term.value.write("\x1b[K"); // \x1b[ 替换为 \x1b 和 [ 的转义字符
  //           term.value.write(currentInput.slice(index));
  //           term.value.write(`\x1B[${currentLength}D`);
  //         } else {
  //           term.value.write(key); // \x1b[ 替换为 \x1b 和 [ 的转义字符
  //         }
  //         // term.value.write(
  //         //   `\x1b[#D\x1b[K${newInput.slice(0, index + 1)}\x1b[${
  //         //     currentInput.length - (index + 1)
  //         //   }C`
  //         // );
  //         // term.value.write(`\x1b[${promptLength + index + 1}G`);
  //       }
  //       break;
  //     // default:
  //     //   if (key.length === 1) {
  //     //     let index = term.value.buffer.active.cursorX - promptLength;
  //     //     currentInput += key;
  //     //     // 将字符串分成两部分，然后插入数字
  //     //     // let newString =
  //     //     //   currentInput.slice(0, index) + key + currentInput.slice(index);

  //     //     // console.log(newString); // 输出: hello123 worldFF

  //     //     console.log("currentInput", currentInput,key);
  //     //     term.value.write(key);
  //     //   }
  //   }
  // });
  term.value.onKey((e) => {
    const ev = e.domEvent;
    const key = ev.key;

    switch (key) {
      case "Enter":
        term.value.write("\r\n");
        handleCommand(currentInput);
        emit("sendCommand", currentInput);
        currentInput = "";
        writePrompt();
        break;

      case "Backspace":
        if (
          currentInput.length > 0 &&
          term.value.buffer.active.cursorX > promptLength
        ) {
          currentInput = currentInput.slice(0, -1);
          term.value.write("\x1B[D\x1B[P\x1B[s\x1B[u");
        }
        break;

      case "ArrowUp":
        if (!ev.shiftKey) {
          navigateHistory(-1);
          ev.preventDefault();
        }
        break;

      case "ArrowDown":
        if (!ev.shiftKey) {
          navigateHistory(1);
          ev.preventDefault();
        }
        break;

      case "ArrowLeft":
        if (term.value.buffer.active.cursorX > promptLength) {
          term.value.write("\x1B[D");
        }
        break;

      case "ArrowRight":
        if (
          term.value.buffer.active.cursorX <
          promptLength + currentInput.length
        ) {
          term.value.write("\x1B[C");
        }
        break;

      case "c":
        if (ev.ctrlKey) {
          ev.preventDefault();
          const selection = term.value.getSelection();
          if (selection) {
            navigator.clipboard.writeText(selection).catch((err) => {
              console.error("复制失败:", err);
            });
          }
          break;
        }
      // 继续到default处理普通'c'键

      case "v":
        if (ev.ctrlKey) {
          ev.preventDefault();
          navigator.clipboard
            .readText()
            .then((text) => {
              const cursorX = term.value.buffer.active.cursorX;
              const index = cursorX - promptLength;
              if (index < 0) return;

              const before = currentInput.slice(0, index);
              const after = currentInput.slice(index);
              currentInput = before + text + after;

              term.value.write(
                "\x1B[s\x1B[K" + text + after + `\x1B[${cursorX + text.length}G`
              );
            })
            .catch((err) => console.error("粘贴失败:", err));
          break;
        }

      default:
        if (key.length === 1 && !ev.ctrlKey && !ev.metaKey && !ev.altKey) {
          let index = term.value.buffer.active.cursorX - promptLength;
          let currentLength = currentInput.length - index;
          let newInput =
            currentInput.slice(0, index) + key + currentInput.slice(index);

          currentInput = newInput;
          if (index < currentInput.length - 1) {
            term.value.write("\x1b[K");
            term.value.write(currentInput.slice(index));
            term.value.write(`\x1B[${currentLength}D`);
          } else {
            term.value.write(key);
          }
        }
        break;
    }
  });
  term.value.writeln("\x1b[38;5;48mWelcome to the enhanced terminal!\x1b[0m");
  term.value.writeln(
    getTimestamp() + "\x1b[38;5;48mType 'help' for available commands\x1b[0m"
  );
  writePrompt();
  // 终端添加focus事件的监听, dispose函数可以取消监听
  console.log("term.value", term.value);
  // 在 `initTerm` 方法中初始化终端后
  const terminalElement = terminal.value; // 获取终端容器的 DOM 元素

  // // 添加聚焦和失焦事件监听器
  terminalElement.addEventListener("click", () => {
    console.log("Terminal gained focus");
    setTimeout(() => {
      emit("handleTer", true);
    }, 100);
  });

  // 移除事件监听器
  onBeforeUnmount(() => {
    window.removeEventListener("resize", onResize);
    term.value.dispose();

    // 移除聚焦和失焦事件监听器
    terminalElement.removeEventListener("focus");
    terminalElement.removeEventListener("blur");
  });
  // term.value.onBlur(() => {
  //   console.log("Terminal lost focus");
  // });
  // term.value.onFocus(() => {
  //   console.log("Terminal gained focus");
  // });
};

// 处理命令
const handleCommand = (command) => {
  commandHistory.value.push(command);
  historyIndex = commandHistory.value.length;

  // 发送命令到后端
  // socket.emit("command", command);

  // 输出本地执行的命令
  // term.value.writeln(
  //   "\x1b[38;5;48m" + getTimestamp() + `Executed: ${command} \x1b[0m`
  // );
  // term.value.writeln(
  //   getTimestamp() + `\x1b[38;5;48mExecuted: ${command}\x1b[0m`
  // );
};

// 历史命令导航
const navigateHistory = (direction) => {
  if (commandHistory.value.length === 0) return;

  historyIndex = Math.max(
    0,
    Math.min(commandHistory.value.length - 1, historyIndex + direction)
  );
  const command = commandHistory.value[historyIndex] || "";

  // 清除当前行并重写
  term.value.write("\x1B[2K\r"); // 清除整行
  writePrompt();
  term.value.write(command);
  currentInput = command;
};

// 调整终端尺寸
const fitTerm = () => fitAddon.fit();
const onResize = debounce(fitTerm, 100);

watch(
  () => props.connectMsg,
  () => {
    console.log(333333333222222, props.connectMsg);

    if (props.connectMsg.length > 0) {
      if (props.connectMsg[props.connectMsg.length - 1].type == "connectMsg") {
        term.value?.writeln(
          `\x1b[38;5;48mExecuted ${
            props.connectMsg[props.connectMsg.length - 1].content
          }\x1b[0m`
        );
      } else {
        term.value?.writeln(
          `\x1b[38;5;117m ${
            props.connectMsg[props.connectMsg.length - 1].content
          }\x1b[0m`
        );
      }
      writePrompt();
    }
  },
  { immediate: true, deep: true } // 深度监听数组变化
);
// 生命周期钩子
onMounted(() => {
  initTerm();
  window.addEventListener("resize", onResize);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", onResize);
  term.value.dispose();
});
</script>

<style scoped>
.terminal-container {
  width: 100%;
  height: 26vh;
  /* height: 80vh; */
  /* height: 45vh; */
  /* height: 59vh; */
  background: #262629;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  overflow: hidden;
  position: relative;
}

.terminal-container ::v-deep .xterm-viewport {
  border-radius: 8px;
  overflow: hidden;
  scrollbar-width: thin; /* Firefox */
}

.terminal-container ::v-deep .xterm-viewport::-webkit-scrollbar {
  width: 8px;
}

.terminal-container ::v-deep .xterm-viewport::-webkit-scrollbar-thumb {
  background-color: #555;
  border-radius: 4px;
}

.terminal-container ::v-deep .xterm-viewport::-webkit-scrollbar-track {
  background: #262629;
}

.xterm-rows {
  font-size: 16px;
  font-weight: 700 !important;
}
.terminal-container ::v-deep .xterm-rows {
  display: flex;
  flex-direction: column;
  text-align: left;
  font-family: "Fira Code", "Monaco", "Hack", monospace;
  font-size: 16px;
  font-weight: 700;
  color: #ececec;
  background: #262629;
}

.terminal-container ::v-deep .xterm-prompt {
  color: #242424;
}
</style>
